﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Text.RegularExpressions;

using Lucene.Net;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Util;

namespace OgilvyOne.UKNow.BLL
{
    public class SearchBll
    {
        /// <summary>
        /// 索引文件路劲
        /// </summary>
        public   string IndexPath { get; set; }
        /// <summary>
        /// 静态文件路径
        /// </summary>
        public  string FilePath { get; set; }
        /// <summary>
        /// 是否创建标识
        /// </summary>
        public  bool IsCreate { get; set; }
        /// <summary>
        /// 搜索关键字
        /// </summary>
        public  string SearchKey { get; set; }
        /// <summary>
        /// 搜索结果数量
        /// </summary>
        public  string ResultCount { get; set; }
        /// <summary>
        /// 搜索结果
        /// </summary>
        public  string SearchResult { get; set; }

        int icount = 0;
        int lineCount;
        public SearchBll()
        {
            if (!string.IsNullOrEmpty( ConfigurationSettings.AppSettings["LineCount"]))
            {
                lineCount = int.Parse(ConfigurationSettings.AppSettings["LineCount"]);
            }
        }
       
        /// <summary>
        /// 创建并返回索引分析器
        /// </summary>
        /// <returns></returns>
        private   Analyzer GetAnalyzer()
        {
            return new StandardAnalyzer();
        }

        /// <summary>
        /// 检索
        /// </summary>
        /// <param name="path_index">索引路径</param>
        /// <param name="key">搜索关键字</param>
        /// <param name="analyzer">分析器</param>
        public void QueryByParagraph()
        {
            IndexSearcher searcher = new IndexSearcher(IndexPath,true);
            Analyzer analyzer = GetAnalyzer();
            BooleanQuery bquery = new BooleanQuery();
            string pathType = string.Empty;
            if (IndexPath.IndexOf("en") > 0)
            {
                pathType = "en";
            }
            else
            {
                pathType = "cn";
            }

            string[] keys = SearchKey.Trim().Split(new char[] { ' ', ',', '，', '、','|'}, StringSplitOptions.RemoveEmptyEntries);
            String[] fields = { "html", "title" };
            foreach(string item in keys)
            {
                if (item != "")
                {
                    BooleanClause.Occur[] flags = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
                    string[] keyword = { item, item };
                    Query query = MultiFieldQueryParser.Parse(keyword, fields, flags, analyzer);
                    bquery.Add(query, BooleanClause.Occur.SHOULD);
                }
            }
            DateTime starttime = new DateTime();

            starttime = DateTime.Now;

            TopDocs topDocs = searcher.Search(bquery, 50);
            ScoreDoc[] docs = topDocs.scoreDocs;
            
            DateTime endtime = new DateTime();

            endtime = DateTime.Now;

            TimeSpan aa = endtime - starttime;

            int se = aa.Milliseconds;//查询花费的时间
           
            ResultCount = docs.Length.ToString();
            StringBuilder sb = new StringBuilder();
          
            for (int i = 0; i < docs.Length; i++)
            {
                icount = 0;
                Document doc = searcher.Doc(docs[i].doc);
                string content = doc.Get("html");
                
                sb.Append("<dl>\n");
                sb.Append("<dt><a href='" + doc.Get("url") + "'>" + doc.Get("title") + "</a></dt>\n");
                content = this.RemoveHTML(content);
                if (content.Length > 270)
                {
                    content = content.Substring(0, 270)+"...";
                }
                foreach (string item in keys)
                {
                    Regex r = new Regex("(?<result>" + item + ")", RegexOptions.IgnoreCase);
                    Match m = r.Match(content);

                    content = r.Replace(content, "<font color=red>${result}</font>");
                }
                sb.Append("<dd>" + content + "</dd>\n");
                //PareseContent(doc,sb, content);
            }
            
            SearchResult = sb.ToString();
            searcher.Close();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="keyValue">关键字</param>
        /// <param name="pageindex">当前页号从0开始</param>
        /// <param name="numinpage">满页条数</param>
        /// <returns></returns>
        public string  SearchValueByKeyinPage(string keyValue,int pageindex,int numinpage)
        {


            pageindex = pageindex+1;
            #region
            IndexSearcher searcher = new IndexSearcher(IndexPath, true);
            Analyzer analyzer = GetAnalyzer();
            BooleanQuery bquery = new BooleanQuery();
            string pathType = string.Empty;
            if (IndexPath.IndexOf("en") > 0)
            {
                pathType = "en";
            }
            else
            {
                pathType = "cn";
            }

            string[] keys = SearchKey.Trim().Split(new char[] { ' ', ',', '，', '、', '|' }, StringSplitOptions.RemoveEmptyEntries);
            String[] fields = { "html", "title" };
            foreach (string item in keys)
            {
                if (item != "")
                {
                    BooleanClause.Occur[] flags = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
                    string[] keyword = { item, item };
                    Query query = MultiFieldQueryParser.Parse(keyword, fields, flags, analyzer);
                    bquery.Add(query, BooleanClause.Occur.SHOULD);
                }
            }
            DateTime starttime = new DateTime();

            starttime = DateTime.Now;

            TopDocs topDocs = searcher.Search(bquery, 50);
            ScoreDoc[] docs = topDocs.scoreDocs;

            DateTime endtime = new DateTime();

            endtime = DateTime.Now;

            TimeSpan aa = endtime - starttime;

            int se = aa.Milliseconds;//查询花费的时间

            ResultCount = docs.Length.ToString();
            StringBuilder sb = new StringBuilder();
            
            int b = (pageindex - 1) * numinpage;
            int a=b+numinpage-1;
            if (a>=docs.Length) 
                a = docs.Length - 1;

            for (int i = b; i < (a+1); i++)
            {
                icount = 0;
                Document doc = searcher.Doc(docs[i].doc);
                string content = doc.Get("html");

                sb.Append("<dl>\n");
                sb.Append("<dt><a href='" + doc.Get("url") + "'>" + doc.Get("title") + "</a></dt>\n");
                content = this.RemoveHTML(content);
                if (content.Length > 270)
                {
                    content = content.Substring(0, 270) + "...";
                }
                foreach (string item in keys)
                {
                    Regex r = new Regex("(?<result>" + item + ")", RegexOptions.IgnoreCase);
                    Match m = r.Match(content);

                    content = r.Replace(content, "<font color=red>${result}</font>");
                }
                sb.Append("<dd>" + content + "</dd>\n");
                //PareseContent(doc,sb, content);
            }

            int total = docs.Length;
            int pageNumb = 0;
            if (total % numinpage == 0)
            {
                pageNumb = total / numinpage;
            }
            else
            {
                pageNumb = total / numinpage + 1;
            }
            sb.Append("<div class=\"resultpage\">\n");
            sb.Append("<ol>\n");
            if((pageindex-1)<=0)
            {
                sb.Append("<li><a href='search.aspx?type=0&currIndex=0&keywords=" + keyValue + "'><img src='images/icon_comment_pre.gif' alt='' /></a></li>\n");
            }
            else
            {
                sb.Append("<li><a href='search.aspx?type=0&currIndex=" + (pageindex - 1) + "&keywords=" + keyValue + "'><img src='images/icon_comment_pre.gif' alt='' /></a></li>\n");
            }
            for (int j = 0; j < pageNumb; j++)
            {
                sb.Append("<li><a href='search.aspx?type=0&currIndex=" + (j) + "&keywords=" + keyValue + "'>" + (j+1) + "</a></li>\n");
            }
            if (pageindex+1 >= pageNumb)
            {
                sb.Append("<li><a href='search.aspx?type=0&currIndex=" + (pageindex-1) + "&keywords=" + keyValue + "'><img src='images/icon_comment_next.gif' alt='' /></a></li>\n");
            }
            else
            {
                sb.Append("<li><a href='search.aspx?type=0&currIndex=" + (pageindex + 1) + "&keywords=" + keyValue + "'><img src='images/icon_comment_next.gif' alt='' /></a></li>\n");
            }
            sb.Append("</ol>\n");
            sb.Append("</div>\n");



           string  pageResult = sb.ToString();

           searcher.Close();
           return pageResult;
            #endregion


        }

        private string RemoveHTML(string Htmlstring)
        {
            ////删除脚本   
            Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*>(?:.|[\r\n])*?</script>", "", RegexOptions.Multiline); 
            
            //删除HTML   
            Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);

            Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", "   ", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);

            Htmlstring.Replace("<", "");
            Htmlstring.Replace(">", "");
            Htmlstring.Replace("\r\n", "");
            //Htmlstring = HttpContext.Current.Server.HtmlEncode(Htmlstring).Trim();

            return Htmlstring;
        }
       
        private void   PareseContent(Document doc,StringBuilder sb, string content)
        {
            string strResult = string.Empty;
            int startPos = content.LastIndexOf("<p>");
            int count = content.Length - startPos;
            if (icount >= lineCount)
            {
                sb.Append("</dl>\n");
                return;
            }
            if (startPos != -1)
            {
                string tmpContent = content.Substring(startPos,count);

                string[] arrkeywords = SearchKey.Trim().Split(new char[] { ' ', ',', '，', '、', '|' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string item in arrkeywords)
                {
                    if (tmpContent.ToUpper().Contains(item.ToUpper()))
                    {
                        int pos=tmpContent.IndexOf("<a");
                        if (pos > 0)
                        {
                            tmpContent = tmpContent.Substring(0, pos - 1);
                        }
                        if (tmpContent.Length > 270)
                        {
                            tmpContent = this.RemoveHTML(tmpContent);
                            if (tmpContent.Length > 270)
                            {
                                strResult = tmpContent.Substring(0, 270) + "...</p>";
                            }
             
                            sb.Append("<dd>" + strResult + "</dd>\n");
                        }
                        else
                        {
                            sb.Append("<dd>" + tmpContent + "</dd>\n");
                        }
                        icount++;
                    }
                }

                PareseContent(doc, sb, content.Remove(startPos, count));
            }
        }
    }
}
